home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmigaPlus / Demos / fxPAINT_Demo / InstallData / Amithlon / run_elf-1.7 / src / run_elf.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-13  |  27.9 KB  |  1,235 lines

  1. /*
  2.      RUN_ELF - Load and execute big endian ix86 ELF binaries
  3.      Copyright (C) 2001-2002 Martin Blom <martin@blom.org>
  4.      
  5.      This program is free software; you can redistribute it and/or
  6.      modify it under the terms of the GNU General Public License
  7.      as published by the Free Software Foundation; either version 2
  8.      of the License, or (at your option) any later version.
  9.      
  10.      This program is distributed in the hope that it will be useful,
  11.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.      GNU General Public License for more details.
  14.      
  15.      You should have received a copy of the GNU General Public License
  16.      along with this program; if not, write to the Free Software
  17.      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19.  
  20. #include <exec/types.h>
  21. #include <exec/execbase.h>
  22. #include <exec/memory.h>
  23. #include <exec/resident.h>
  24. #include <proto/exec.h>
  25. #include <proto/dos.h>
  26. #include <proto/intuition.h>
  27.  
  28. #include <stdio.h>
  29. #include <Amielf.h>
  30.  
  31. #include "run_elf86.h"
  32.  
  33. // This flag is called RTF_PPC in MorphOS.
  34. #define RTF_NATIVE (1<<3)
  35.  
  36. #ifndef FUNCARRAY_32BIT_NATIVE
  37. #define FUNCARRAY_32BIT_NATIVE 0xfffefffe
  38. #endif
  39.  
  40. #include <CompilerSpecific.h>
  41.  
  42. #include "elfloader.h"
  43.  
  44. #define bswap_long(x) \
  45.      ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
  46.       (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
  47.  
  48. //#define DEBUG
  49.  
  50. #define VERSION  1
  51. #define REVISION 7
  52. #define VSTRING  "1.7 (13.11.2002)"
  53.  
  54. const char vstr[] = "$VER: run_elf " VSTRING "\r\n";
  55.  
  56. struct Library* _amithlon = NULL;
  57.  
  58. void* Regs = NULL;
  59.  
  60. /*** SegTracker stuff ********************************************************/
  61.  
  62. typedef char* ASMCALL
  63. SegTrack( REG( a0, ULONG  Address ),
  64.       REG( a1, ULONG* SegNum ),
  65.       REG( a2, ULONG* Offset ) );
  66.  
  67. struct  SegSem
  68. {
  69.     struct  SignalSemaphore seg_Semaphore;
  70.     SegTrack*               seg_Find;
  71. };
  72.  
  73. /*** Identification semaphore ************************************************/
  74.  
  75. struct RunELF86
  76. {
  77.     struct SignalSemaphore Semaphore;
  78.     UWORD                  Version;
  79.     UWORD                  Revision;
  80. };
  81.  
  82. /*** Stuff that should really have been in a link library ********************/
  83.  
  84. static UWORD rawputchar_m68k[] __attribute__ ((aligned (4))) = 
  85. {
  86.   0x2C4B,             // MOVEA.L A3,A6
  87.   0x4EAE, 0xFDFC,     // JSR     -$0204(A6)
  88.   0x4E75              // RTS
  89. };
  90.  
  91. void
  92. KPrintFArgs( UBYTE* fmt, 
  93.              ULONG* args )
  94. {
  95.   RawDoFmt( fmt, args, (void(*)(void)) rawputchar_m68k, SysBase );
  96. }
  97.  
  98. #define KPrintF( fmt, ... )        \
  99. ({                                 \
  100.   ULONG _args[] = { __VA_ARGS__ }; \
  101.   KPrintFArgs( (fmt), _args );     \
  102. })
  103.  
  104.  
  105. /*** Display a requester *****************************************************/
  106.  
  107. void
  108. ReqA( const char* text, APTR args )
  109. {
  110.   struct EasyStruct es = 
  111.   {
  112.     sizeof (struct EasyStruct),
  113.     0,
  114.     (STRPTR) "run_elf",
  115.     (STRPTR) text,
  116.     "OK"
  117.   };
  118.  
  119.   EasyRequestArgs( NULL, &es, NULL, args );
  120. }
  121.  
  122. #define Req( fmt, ... )            \
  123. ({                                 \
  124.   ULONG _args[] = { __VA_ARGS__ }; \
  125.   ReqA( (fmt), _args );            \
  126. })
  127.  
  128. /*** A couple of native x86 functiond ****************************************/
  129.  
  130. typedef APTR ASMCALL
  131. CallNativeInitFunction_proto( REG( d0, struct Library*  library ),
  132.                   REG( d1, BPTR             segList ),
  133.                   REG( d2, struct ExecBase* execbase),
  134.                   REG( a0, APTR             init ) );
  135.  
  136. typedef struct GuardContext* ASMCALL
  137. GuardEnable_proto( void );
  138.  
  139. typedef void ASMCALL
  140. GuardDisable_proto( REG( d0, struct GuardContext* ) );
  141.  
  142. CallNativeInitFunction_proto* CallNativeInitFunction = NULL;
  143. GuardEnable_proto*            GuardEnable            = NULL;
  144. GuardDisable_proto*           GuardDisable           = NULL;
  145.  
  146.  
  147. /*** Autoinit funtion definitions ********************************************/
  148.  
  149. typedef APTR ASMCALL
  150. InitFunction_proto( REG( d0, struct Library*  library ),
  151.                     REG( a0, BPTR             segList ),
  152.                     REG( a6, struct ExecBase* execbase) );
  153.  
  154. /*** exec.library patch definitions ******************************************/
  155.  
  156. #define _LVOMakeLibrary     (-84)
  157. #define _LVOMakeFunctions   (-90)
  158. #define _LVOInitResident    (-102)
  159.  
  160. ULONG ASMCALL
  161. MyMakeFunctions( REG( a0, APTR target ),
  162.                  REG( a1, APTR functionArray ),
  163.                  REG( a2, APTR funcDispBase ) );
  164.  
  165. struct Library* ASMCALL
  166. MyMakeLibrary( REG( a0, APTR  vectors ),
  167.                REG( a1, APTR  structure ),
  168.                REG( a2, APTR  init ),
  169.                REG( d0, ULONG dSize ),
  170.                REG( d1, BPTR  segList ) );
  171.  
  172. APTR ASMCALL
  173. MyInitResident( REG( a1, struct Resident* resident ),
  174.                 REG( d1, ULONG            segList ) );
  175.  
  176.  
  177. typedef ULONG ASMCALL
  178. MakeFunctions_proto( REG( a0, APTR target ),
  179.                      REG( a1, APTR functionArray ),
  180.                      REG( a2, APTR funcDispBase ) );
  181.  
  182. typedef struct Library* ASMCALL
  183. MakeLibrary_proto( REG( a0, APTR  vectors ),
  184.                    REG( a1, APTR  structure ),
  185.                    REG( a2, APTR  init ),
  186.                    REG( d0, ULONG dSize ),
  187.                    REG( d1, BPTR  segList ) );
  188.  
  189. typedef APTR ASMCALL
  190. InitResident_proto( REG( a1, struct Resident* resident ),
  191.                     REG( d1, ULONG            segList ) );
  192.  
  193.  
  194. MakeFunctions_proto* OldMakeFunctions = NULL;
  195. MakeLibrary_proto*   OldMakeLibrary   = NULL;
  196. InitResident_proto*  OldInitResident  = NULL;
  197.  
  198.  
  199. /*** dos.library patch definitions *******************************************/
  200.  
  201. #define _LVOLoadSeg         (-150)
  202. #define _LVOInternalLoadSeg (-756)
  203. #define _LVONewLoadSeg      (-768)
  204.  
  205.  
  206. BPTR ASMCALL
  207. MyInternalLoadSeg( REG( d0, BPTR  fh ),
  208.                    REG( a0, BPTR  table ),
  209.                    REG( a1, LONG* functionarray ),
  210.                    REG( a2, LONG* stack ) );
  211.  
  212. BPTR ASMCALL
  213. MyLoadSeg( REG( d1, STRPTR name ) );
  214.  
  215. BPTR ASMCALL
  216. MyNewLoadSeg( REG( d1, STRPTR name ),
  217.               REG( d2, struct TagItem* tags ) );
  218.  
  219.  
  220. typedef BPTR ASMCALL 
  221. InternalLoadSeg_proto( REG( d0, BPTR  fh ),
  222.                        REG( a0, BPTR  table ),
  223.                        REG( a1, LONG* functionarray ),
  224.                        REG( a2, LONG* stack ) );
  225.  
  226. typedef BPTR ASMCALL
  227. LoadSeg_proto( REG( d1, STRPTR name ) );
  228.  
  229.  
  230. typedef BPTR ASMCALL
  231. NewLoadSeg_proto( REG( d1, STRPTR name ),
  232.                   REG( d2, struct TagItem* tags ) );
  233.  
  234.  
  235. InternalLoadSeg_proto* OldInternalLoadSeg = NULL;
  236. LoadSeg_proto*         OldLoadSeg         = NULL;
  237. NewLoadSeg_proto*      OldNewLoadSeg      = NULL;
  238.  
  239.  
  240. /*** misc support code *******************************************************/
  241.  
  242. static struct ELFDynSymbols SymTab[] = 
  243. {
  244.   { "_CallFunc68k", NULL },
  245.   { "_CallLib68k",  NULL },
  246.   { NULL,           NULL }
  247. };
  248.  
  249. static BPTR 
  250. LoadELFSeg( STRPTR          name, 
  251.             struct TagItem* tags )
  252. {
  253.   BPTR  s = NULL;
  254.   void* o = NULL;
  255.  
  256.   (void) tags; // Remove warning
  257.  
  258.   o = ELFLoadObject( name, &s, SymTab );
  259.  
  260.   if( o == NULL || s == NULL )
  261.   {
  262.     s = NULL;
  263.   }
  264.   else
  265.   {
  266.     CacheClearU();
  267.   }
  268.  
  269.   ELFUnLoadObject( o );
  270.  
  271.   return s;
  272. }
  273.  
  274.  
  275. void __chkabort(void)
  276. {
  277.   // Disable it, just in case
  278. }
  279.  
  280.  
  281. static struct Node*
  282. FindNode( struct List* list,
  283.           struct Node* node )
  284. {
  285.   struct Node* currentnode;
  286.  
  287.   for( currentnode = list->lh_Head;
  288.        currentnode->ln_Succ != NULL;
  289.        currentnode = currentnode->ln_Succ )
  290.   {
  291.     if( currentnode == node )
  292.     {
  293.       return currentnode;
  294.     }
  295.   }
  296.   
  297.   return NULL;
  298. }
  299.  
  300.  
  301. static void
  302. ShowHit( struct Hit* hit )
  303. {
  304.   int i;
  305.  
  306.   KPrintF( "\nILLEGAL %s %s %08lx %s %08lx (TCB: %08lx)\n",
  307.        (ULONG) (hit->cpu == CPU_M68K ? "M68K" : "IX86"),
  308.        (ULONG) (hit->mode == MODE_READ ? "READ from" : "WRITE to"),
  309.        (ULONG) hit->addr,
  310.        (ULONG) (hit->cpu == CPU_M68K ? "near" : "at" ),
  311.        hit->pc,
  312.        (ULONG) hit->task );
  313.  
  314.  
  315.   if( hit->cpu == CPU_IX86 )
  316.   {
  317.     KPrintF( "EFLAGS: %08lx\n", hit->c.ix86.eflags );
  318.     KPrintF( "      EAX      EBX      ECX      EDX"
  319.          "      ESI      EDI      ESP      EBP\n" );
  320.     KPrintF( "Regs: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
  321.          hit->c.ix86.eax, hit->c.ix86.ebx, hit->c.ix86.ecx, hit->c.ix86.edx,
  322.          hit->c.ix86.esi, hit->c.ix86.edi, hit->c.ix86.esp, hit->c.ix86.ebp );
  323.  
  324.     KPrintF( "Stck:" );
  325.  
  326.     for( i = 0; i < 8; ++i )
  327.     {
  328.       KPrintF( " %08lx", bswap_long( hit->stack[ i ] ) );
  329.     }
  330.  
  331.     KPrintF( "\n     " );
  332.  
  333.     for( i = 8; i < 16; ++i )
  334.     {
  335.       KPrintF( " %08lx", bswap_long( hit->stack[ i ] ) );
  336.     }
  337.  
  338.     KPrintF( "\nStck:" );
  339.  
  340.     for( i = 0; i < 8; ++i )
  341.     {
  342.       KPrintF( " %08lx", hit->stack[ i ] );
  343.     }
  344.  
  345.     KPrintF( "\n[BE] " );
  346.  
  347.     for( i = 8; i < 16; ++i )
  348.     {
  349.       KPrintF( " %08lx", hit->stack[ i ] );
  350.     }
  351.   }
  352.   else
  353.   {
  354.     KPrintF( "SR:%04lx\n", hit->c.m68k.sr );
  355.     KPrintF( "Data:" );
  356.  
  357.     for( i = 0; i < 8; ++i )
  358.     {
  359.       KPrintF( " %08lx", hit->c.m68k.dregs[ i ] );
  360.     }
  361.     
  362.     KPrintF( "\nAddr:" );
  363.  
  364.     for( i = 0; i < 8; ++i )
  365.     {
  366.       KPrintF( " %08lx", hit->c.m68k.aregs[ i ] );
  367.     }
  368.  
  369.     KPrintF( "\nStck:" );
  370.  
  371.     for( i = 0; i < 8; ++i )
  372.     {
  373.       KPrintF( " %08lx", hit->stack[ i ] );
  374.     }
  375.  
  376.     KPrintF( "\n     " );
  377.  
  378.     for( i = 8; i < 16; ++i )
  379.     {
  380.       KPrintF( " %08lx", hit->stack[ i ] );
  381.     }
  382.   }
  383.   
  384.   KPrintF( "\n%s", (ULONG) hit->disasm );
  385.  
  386.   Forbid();
  387.  
  388.   {
  389.     struct SegSem* seg_sem;
  390.     ULONG seg_num   = 0;
  391.     ULONG offset    = 0;
  392.     char* file_name = NULL;
  393.  
  394.     seg_sem = (struct SegSem*) FindSemaphore( "SegTracker" );
  395.  
  396.     if( seg_sem != NULL )
  397.     {
  398.       if( seg_sem->seg_Find != NULL )
  399.       {
  400.     file_name = seg_sem->seg_Find( hit->pc, &seg_num, &offset );
  401.  
  402.     if( file_name != NULL )
  403.     {
  404.       KPrintF( "----> %08lx - \"%s\"  Hunk %04lx Offset %08lx\n",
  405.            hit->pc, (ULONG) file_name, seg_num, offset );
  406.     }
  407.       }
  408.     }
  409.  
  410.     // See if the task is still around
  411.  
  412.     if( FindNode( &SysBase->TaskReady, (struct Node*) hit->task ) != NULL ||
  413.     FindNode( &SysBase->TaskWait, (struct Node*) hit->task ) != NULL )
  414.     {
  415.       struct Process* proc = (struct Process*) hit->task;
  416.  
  417.       KPrintF( "Name: \"%s\"", (ULONG) proc->pr_Task.tc_Node.ln_Name );
  418.  
  419.       if( proc->pr_Task.tc_Node.ln_Type == NT_PROCESS &&
  420.       proc->pr_TaskNum != 0 )
  421.       {
  422.     struct CommandLineInterface* cli = BADDR( proc->pr_CLI );
  423.  
  424.     if( cli->cli_Module != NULL )
  425.     {
  426.       KPrintF( "  CLI: \"%b\"", cli->cli_CommandName );
  427.     }
  428.  
  429.     if( file_name != NULL )
  430.     {
  431.       KPrintF( "  Hunk %04lx Offset %08lx\n",
  432.            seg_num, offset );
  433.       
  434.     }
  435.       }
  436.  
  437.       KPrintF( "\n" );
  438.     }
  439.   }
  440.   
  441.   Permit();
  442.   
  443. }
  444.   
  445.  
  446.  
  447. /*** main() ******************************************************************/
  448.  
  449. int
  450. main( void )
  451. {
  452.   int rc = 0;
  453.  
  454.   if( sizeof( struct Hit ) != 1024 )
  455.   {
  456.     Printf( "sizeof( struct Hit ) == %ld\n", sizeof( struct Hit ) );
  457.     return 20;
  458.   }
  459.   
  460.   _amithlon = OpenResource( "amithlon.resource" );
  461.  
  462. //  if( _amithlon == NULL )
  463. //  {
  464. //    _amithlon = OpenResource( "amithlon.resource" );
  465. //  }
  466.   
  467.   if( _amithlon == NULL )
  468.   {
  469.     Printf( "This program is for Amithlon only.\n" );
  470.     rc = 20;
  471.   }
  472.   else
  473.   {
  474.     void* run_elf86;
  475.  
  476.     run_elf86 = open_elf( "PROGDIR:run_elf86" );
  477.  
  478.     if( run_elf86 == NULL )
  479.     {
  480.       Printf( "Unable to load ix86 native functions from 'run_elf86'.\n" );
  481.       rc = 20;
  482.     }
  483.     else
  484.     {
  485.       struct ELFDynSymbols* stab = SymTab;
  486.  
  487.       // Get the emulations register storage address
  488.  
  489.       Regs = find_symbol( NULL, "regs" );
  490.  
  491.       if( Regs == NULL )
  492.       {
  493.     Printf( "Unable to find symbol 'regs'.\n" );
  494.     rc = 20;
  495.       }
  496.  
  497.       // Load symbols from 'run_elf86'
  498.  
  499.       CallNativeInitFunction = (CallNativeInitFunction_proto*)
  500.     find_slowcall( run_elf86, "CallNativeInitFunction" );
  501.  
  502.       GuardEnable = (GuardEnable_proto*)
  503.     find_slowcall( run_elf86, "GuardEnable" );
  504.       
  505.       GuardDisable = (GuardDisable_proto*)
  506.     find_slowcall( run_elf86, "GuardDisable" );
  507.  
  508.       if( CallNativeInitFunction == NULL )
  509.       {
  510.     Printf( "Unable to find symbol 'CallNativeInitFunction'.\n" );
  511.     rc = 20;
  512.       }
  513.  
  514.       if( GuardEnable == NULL )
  515.       {
  516.     Printf( "Unable to find symbol 'GuardEnable'.\n" );
  517.     rc = 20;
  518.       }
  519.  
  520.       if( GuardDisable == NULL )
  521.       {
  522.     Printf( "Unable to find symbol 'GuardDisable'.\n" );
  523.     rc = 20;
  524.       }
  525.  
  526.       // Load all symbols that will be resolved by the ELF loader
  527.       
  528.       while( stab->name != NULL )
  529.       {
  530.     stab->addr = find_symbol( run_elf86, stab->name );
  531.  
  532.     if( stab->addr == NULL )
  533.     {
  534.       Printf( "Unable to find symbol '%s'.\n",
  535.           (ULONG) stab->name );
  536.       rc = 20;
  537.     }
  538.       
  539.     ++stab;
  540.       }
  541.  
  542.       if( rc == 0 )
  543.       {
  544.     struct RDArgs* ra = NULL;
  545.     struct
  546.     {
  547.         STRPTR file;
  548.         ULONG  guard;
  549.         ULONG  patch;
  550.         STRPTR args;
  551.     } args = { NULL, FALSE, FALSE, "" };
  552.  
  553.     ra = ReadArgs( "FILE,GUARD/S,PATCH/S,ARGS/F", (ULONG*) &args, NULL );
  554.  
  555.     if( ra == NULL || 
  556.         ( args.file == NULL && ! args.patch) || 
  557.         ( args.file != NULL && args.patch ) )
  558.     {
  559.       Printf( "Usage: run_elf [GUARD] <program> [<arguments>]\n" );
  560.       Printf( "   or: run_elf [GUARD] PATCH\n" );
  561.       rc = 20;
  562.     }
  563.     else
  564.     {
  565.       struct GuardContext* guard_context = NULL;
  566.       
  567.       if( args.guard )
  568.       {
  569.         guard_context = GuardEnable();
  570.  
  571.         if( guard_context == NULL )
  572.         {
  573.           Printf( "Unable to install guard.\n" );
  574.         }
  575.       }
  576.       
  577.       if( args.patch )
  578.       {
  579.         struct MsgPort*  setman;
  580.         struct RunELF86* semaphore;
  581.  
  582.         semaphore = AllocVec( sizeof( *semaphore),
  583.                   MEMF_PUBLIC | MEMF_CLEAR );
  584.  
  585.         if( semaphore != NULL )
  586.         {
  587.           semaphore->Semaphore.ss_Link.ln_Name = "RunELF86";
  588.           semaphore->Semaphore.ss_Link.ln_Pri  = -127;
  589.           semaphore->Version                   = VERSION;
  590.           semaphore->Revision                  = REVISION;
  591.         }
  592.         
  593.         // Avoid race conditions when patching:
  594.         Forbid();
  595.  
  596.         // Ah, I just love SetFunction(). Don't you agree, Frieden?
  597.         // SCNR ... :-)
  598.  
  599.         OldMakeFunctions = (MakeFunctions_proto*)
  600.           SetFunction( (struct Library*) SysBase,
  601.                _LVOMakeFunctions,
  602.                (ULONG (*)(void)) MyMakeFunctions );
  603.  
  604.         OldMakeLibrary = (MakeLibrary_proto*)
  605.           SetFunction( (struct Library*) SysBase,
  606.                _LVOMakeLibrary,
  607.                (ULONG (*)(void)) MyMakeLibrary );
  608.  
  609.         OldInitResident = (InitResident_proto*)
  610.           SetFunction( (struct Library*) SysBase,
  611.                _LVOInitResident,
  612.                (ULONG (*)(void)) MyInitResident );
  613.  
  614. //          OldInternalLoadSeg = (InternalLoadSeg_proto*)
  615. //            SetFunction( (struct Library*) DOSBase, 
  616. //                         _LVOInternalLoadSeg,
  617. //                         (ULONG (*)(void)) MyInternalLoadSeg );
  618.  
  619.         OldLoadSeg = (LoadSeg_proto*)
  620.           SetFunction( (struct Library*) DOSBase, 
  621.                _LVOLoadSeg,
  622.                (ULONG (*)(void)) MyLoadSeg );
  623.  
  624.         OldNewLoadSeg = (NewLoadSeg_proto*)
  625.           SetFunction( (struct Library*) DOSBase, 
  626.                _LVONewLoadSeg,
  627.                (ULONG (*)(void)) MyNewLoadSeg );
  628.  
  629.         if( semaphore != NULL )
  630.         {
  631.           AddSemaphore( &semaphore->Semaphore );
  632.         }
  633.         
  634.         setman = FindPort( "SetMan" );
  635.         
  636.         while( TRUE )
  637.         {
  638.           ULONG signals;
  639.  
  640.           // Temporary break the Forbid() state
  641.           Delay( 1 );
  642.  
  643.           signals = SetSignal( 0,
  644.                    SIGBREAKF_CTRL_C |
  645.                    SIGBREAKF_CTRL_E |
  646.                    SIGBREAKF_CTRL_F );
  647.  
  648.           if( signals & SIGBREAKF_CTRL_C )
  649.           {
  650.         if( setman != NULL )
  651.         {
  652.           break;
  653.         }
  654.         else
  655.         {
  656.           Printf( "Can't terminate since PatchControl is not running.\n" );
  657.         }
  658.           }
  659.  
  660.           if( signals & SIGBREAKF_CTRL_E )
  661.           {
  662.         if( guard_context == NULL )
  663.         {
  664.           guard_context = GuardEnable();
  665.  
  666.           if( guard_context != NULL )
  667.           {
  668.             Printf( "Guard installed.\n" );
  669.           }
  670.           else
  671.           {
  672.             Printf( "Unable to install guard.\n" );
  673.           }
  674.         }
  675.         else
  676.         {
  677.           Printf( "Guard already installed.\n" );
  678.         }
  679.           }
  680.  
  681.           if( signals & SIGBREAKF_CTRL_F )
  682.           {
  683.         if( guard_context != NULL )
  684.         {
  685.           GuardDisable( guard_context );
  686.           guard_context = NULL;
  687.           Printf( "Guard removed.\n" );
  688.         }
  689.         else
  690.         {
  691.           Printf( "Guard already removed.\n" );
  692.         }
  693.           }
  694.  
  695.           if( guard_context != NULL )
  696.           {
  697.         while( guard_context->read_index != guard_context->write_index )
  698.         {
  699.           ShowHit( &guard_context->hits[ guard_context->read_index ] );
  700.           
  701.           ++guard_context->read_index;
  702.         }
  703.           }
  704.           
  705.         }
  706.  
  707.         if( semaphore != NULL )
  708.         {
  709.           // Disables Forbid() state while waiting.
  710.           ObtainSemaphore( &semaphore->Semaphore );
  711.  
  712.           // Forbid() is active again!
  713.           ReleaseSemaphore( &semaphore->Semaphore );
  714.           RemSemaphore( &semaphore->Semaphore );
  715.           FreeVec( semaphore );
  716.         }
  717.  
  718.         SetFunction( (struct Library*) SysBase,
  719.              _LVOMakeFunctions,
  720.              (ULONG (*)(void)) OldMakeFunctions );
  721.  
  722.         SetFunction( (struct Library*) SysBase,
  723.              _LVOMakeLibrary,
  724.              (ULONG (*)(void)) OldMakeLibrary );
  725.  
  726.         SetFunction( (struct Library*) SysBase,
  727.              _LVOInitResident,
  728.              (ULONG (*)(void)) OldInitResident );
  729.  
  730. //          SetFunction( (struct Library*) DOSBase,
  731. //                       _LVOInternalLoadSeg,
  732. //                       (ULONG (*)(void)) OldInternalLoadSeg );
  733.  
  734.         SetFunction( (struct Library*) DOSBase,
  735.              _LVOLoadSeg,
  736.              (ULONG (*)(void)) OldLoadSeg );
  737.  
  738.         SetFunction( (struct Library*) DOSBase,
  739.              _LVONewLoadSeg,
  740.              (ULONG (*)(void)) OldNewLoadSeg );
  741.  
  742.         Permit();
  743.       }
  744.       else
  745.       {
  746.         BPTR s = NULL;
  747.  
  748.         s = LoadELFSeg( args.file, NULL );
  749.  
  750.         if( s == 0 )
  751.         {
  752.           Printf( "Unable to load ELF object %s\n", (ULONG) args.file );
  753.           rc = 20;
  754.         }
  755.         else
  756.         {
  757.           int   cmdlen  = strlen( args.args ) + 1;
  758.           char* cmdline;
  759.  
  760.           cmdline = AllocVec( cmdlen + 1, MEMF_ANY );
  761.  
  762.           if( cmdline == NULL )
  763.           {
  764.         Printf( "Out of memory.\n" );
  765.         rc = 20;
  766.           }
  767.           else
  768.           {
  769.         struct Task* me = FindTask( NULL );
  770.  
  771.         strcpy( cmdline, args.args );
  772.         cmdline[ cmdlen - 1 ] = '\n';
  773.         cmdline[ cmdlen ] = 0;
  774.  
  775.         SetProgramName( args.file );
  776.         rc = RunCommand( s, 
  777.                  me->tc_SPUpper - me->tc_SPLower, 
  778.                  cmdline, cmdlen );
  779.  
  780.         FreeVec( cmdline );
  781.           }
  782.  
  783.           UnLoadSeg( s );
  784.         }
  785.       }
  786.  
  787.       if( guard_context != NULL )
  788.       {
  789.         GuardDisable( guard_context );
  790.       }
  791.     }
  792.  
  793.     FreeArgs( ra );
  794.       }
  795.  
  796.       close_elf( run_elf86 );
  797.     }
  798.   }
  799.  
  800.   return rc;
  801. }
  802.  
  803.  
  804. /*** exec.library patches follows ********************************************/
  805.  
  806. static APTR
  807. CallInitFunc( struct Resident* resident,
  808.               APTR             init,
  809.               struct Library*  library,
  810.               BPTR             segList )
  811. {
  812.   APTR res;
  813.   
  814. #ifdef DEBUG
  815.   KPrintF( "CallInitFunc( 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx )\n",
  816.        (ULONG) resident, (ULONG) init, (ULONG) library, segList );
  817. #endif
  818.  
  819.   if( resident->rt_Flags & RTF_NATIVE )
  820.   {
  821. //  __asm__("illegal");
  822.     res = CallNativeInitFunction( library, segList, SysBase, init );
  823. //  __asm__("illegal");
  824.   }
  825.   else
  826.   {
  827.     InitFunction_proto* i = (InitFunction_proto*) init;
  828.  
  829.     res = i( library, segList, SysBase );
  830.   }
  831.  
  832. #ifdef DEBUG
  833.   KPrintF( "CallInitFunc -> 0x%08lx\n", (ULONG) res );
  834. #endif
  835.  
  836.   return res;
  837. }
  838.  
  839.  
  840. struct EntryTrampoline
  841. {
  842.     UBYTE mov;
  843.     ULONG regs;
  844.     UBYTE jmp;
  845.     ULONG addr;
  846.     UBYTE nop1;
  847.     UBYTE nop2;
  848. } __attribute__((packed));
  849.  
  850.  
  851. #define SET_ENTRYTRAMPOLINE(tp,funcptr)                                 \
  852.  ((struct EntryTrampoline*) tp)->mov  = 0xb8;                           \
  853.  ((struct EntryTrampoline*) tp)->regs = bswap_long( (ULONG) Regs );     \
  854.  ((struct EntryTrampoline*) tp)->jmp  = 0xe9;                           \
  855.  ((struct EntryTrampoline*) tp)->addr = bswap_long( (ULONG) (funcptr) - \
  856.                                                     10 - (ULONG) (tp) );\
  857.  ((struct EntryTrampoline*) tp)->nop1 = 0x90;                           \
  858.  ((struct EntryTrampoline*) tp)->nop2 = 0x90;
  859.  
  860. struct JumpVec
  861. {
  862.     unsigned short jmp;
  863.     unsigned char vec[4];
  864. };
  865.  
  866. #define __AROS_ASMJMP                   0x4EF9
  867. #define __AROS_SET_VEC(v,a)             (*(ULONG*)(v)->vec=(ULONG)(a))
  868. #define __AROS_GET_VEC(v)               ((APTR)(*(ULONG*)(v)->vec))
  869. #define __AROS_GETJUMPVEC(lib,n)        ((struct JumpVec *)(((UBYTE *)lib)-(n*LIB_VECTSIZE)))
  870. #define __AROS_GETVECADDR(lib,n)        (__AROS_GET_VEC(__AROS_GETJUMPVEC(lib,n)))
  871. #define __AROS_SETVECADDR(lib,n,addr)   (__AROS_SET_VEC(__AROS_GETJUMPVEC(lib,n),(APTR)(addr)))
  872. #define __AROS_INITVEC(lib,n)           __AROS_GETJUMPVEC(lib,n)->jmp = __AROS_ASMJMP, \
  873.                                         __AROS_SETVECADDR(lib,n,0)
  874. ULONG ASMCALL
  875. MyMakeFunctions( REG( a0, APTR target ),
  876.                  REG( a1, APTR functionArray ),
  877.                  REG( a2, APTR funcDispBase ) )
  878. {
  879.   /* This code is from AROS, except for the FUNCARRAY_32BIT_NATIVE part. */
  880.  
  881.   long n;
  882. //  APTR lastvec;
  883.  
  884. #ifdef DEBUG
  885.   KPrintF( "MyMakeFunctions( 0x%08lx, 0x%08lx, 0x%08lx )\n",
  886.            (ULONG) target, (ULONG) functionArray, (ULONG) funcDispBase );
  887. #endif
  888.  
  889.   n = 1;
  890.  
  891.   if (funcDispBase!=NULL)
  892.   {
  893.     /* If FuncDispBase is non-NULL it's an array of relative offsets */
  894.     WORD *fp=(WORD *)functionArray;
  895.  
  896.     /* -1 terminates the array */
  897.     while(*fp!=-1)
  898.     {
  899.       /* Decrement vector pointer by one and install vector */
  900.       __AROS_INITVEC(target,n);
  901.       if (*fp)
  902.         __AROS_SETVECADDR(target,n,funcDispBase+*fp);
  903.  
  904.       /* Use next array entry */
  905.       fp++;
  906.       n++;
  907.     }
  908.   }
  909.   else
  910.   {
  911.     /* If FuncDispBase is NULL it's an array of function pointers */
  912.     void **fp=(void **)functionArray;
  913.  
  914.     if( *fp == (void*) FUNCARRAY_32BIT_NATIVE )
  915.     {
  916.       struct EntryTrampoline* tp = (struct EntryTrampoline*)
  917.           ( (ULONG) target - ((struct Library*) target)->lib_NegSize );
  918.  
  919.       ++fp;
  920.       
  921.       /* -1 terminates the array */
  922.       while(*fp!=(void *)-1)
  923.       {
  924.         /* Decrement vector pointer by one and install vector */
  925.         __AROS_INITVEC(target,n);
  926.     if( _amithlon->lib_Version < 2 )
  927.     {
  928.       if (*fp)
  929.         __AROS_SETVECADDR(target,n,(ULONG)tp|0x00000001); // "slowcall"
  930.  
  931.       /* Install trampoline */
  932.       SET_ENTRYTRAMPOLINE(tp,*fp);
  933.  
  934.       tp++;
  935.     }
  936.     else
  937.     {
  938.       if (*fp)
  939.         __AROS_SETVECADDR(target,n,(ULONG)*fp|0x80000001); // "bslowcall"
  940.     }
  941.       
  942.  
  943.         /* Use next array entry */
  944.         fp++;
  945.         n++;
  946.       }
  947.     }
  948.     else
  949.     {
  950.       /* -1 terminates the array */
  951.       while(*fp!=(void *)-1)
  952.       {
  953.         /* Decrement vector pointer by one and install vector */
  954.         __AROS_INITVEC(target,n);
  955.         if (*fp)
  956.           __AROS_SETVECADDR(target,n,*fp);
  957.  
  958.         /* Use next array entry */
  959.         fp++;
  960.         n++;
  961.       }
  962.     }
  963.   }
  964.  
  965.   n = ((struct Library*) target)->lib_NegSize;
  966.  
  967.   /* Clear instruction cache for the whole jumptable and trampolines */
  968.   CacheClearE(target - n, n, CACRF_ClearI|CACRF_ClearD);
  969.  
  970. #ifdef DEBUG
  971.   KPrintF( "MyMakeFunctions -> 0x%ld\n", n );
  972. #endif
  973.   
  974.   /* Return size of jumptable */
  975.   return n;
  976. }
  977.  
  978. struct Library* ASMCALL
  979. MyMakeLibrary( REG( a0, APTR  vectors ),
  980.                REG( a1, APTR  structure ),
  981.                REG( a2, APTR  init ),
  982.                REG( d0, ULONG dSize ),
  983.                REG( d1, BPTR  segList ) )
  984. {
  985.   /* This code is from AROS, except for the FUNCARRAY_32BIT_NATIVE part. */
  986.  
  987.   struct Library *library;
  988.   ULONG negsize=0;
  989.  
  990. #ifdef DEBUG
  991.   KPrintF( "MyMakeLibrary( 0x%08lx, 0x%08lx, 0x%08lx, %ld, %08lx )\n",
  992.            (ULONG) vectors, (ULONG) structure, (ULONG) init, dSize,
  993.        (ULONG) segList );
  994. #endif
  995.  
  996.   /* Calculate the jumptable's size */
  997.   if(*(WORD *)vectors==-1)
  998.   {
  999.     /* Count offsets */
  1000.     WORD *fp=(WORD *)vectors+1;
  1001.     while(*fp++!=-1)
  1002.       negsize+=LIB_VECTSIZE;
  1003.   }
  1004.   else
  1005.   {
  1006.     /* Count function pointers */
  1007.     void **fp=(void **)vectors;
  1008.     
  1009.     if( *fp == (void*) FUNCARRAY_32BIT_NATIVE )
  1010.     {
  1011.       fp++;
  1012.  
  1013.       while( *fp != (void *) -1 )
  1014.       {
  1015.         negsize += LIB_VECTSIZE;
  1016.     if( _amithlon->lib_Version < 2 )
  1017.     {
  1018.       negsize += sizeof( struct EntryTrampoline );
  1019.     }
  1020.         ++fp;
  1021.       }
  1022.     }
  1023.     else
  1024.     {
  1025.       while(*fp++!=(void *)-1)
  1026.         negsize+=LIB_VECTSIZE;
  1027.     }
  1028.   }
  1029.  
  1030.   /* Align library base */
  1031.   negsize=(negsize+3)&~3;
  1032.  
  1033.   /* Allocate memory */
  1034.   library=(struct Library *)AllocMem(dSize+negsize,MEMF_PUBLIC|MEMF_CLEAR);
  1035.  
  1036.   /* And initilize the library */
  1037.   if(library!=NULL)
  1038.   {
  1039.     /* Get real library base */
  1040.     library=(struct Library *)((char *)library+negsize);
  1041.  
  1042.     /* Write sizes *before* MakeFunctions!! */
  1043.     library->lib_NegSize=negsize;
  1044.     library->lib_PosSize=dSize;
  1045.  
  1046.     /* Build jumptable */
  1047.     if(*(WORD *)vectors==-1)
  1048.       /* offsets */
  1049.       MakeFunctions(library,(WORD *)vectors+1,(ULONG)vectors);
  1050.     else
  1051.       /* function pointers */
  1052.       MakeFunctions(library,vectors,NULL);
  1053.  
  1054.     /* Create structure */
  1055.     if(structure!=NULL)
  1056.       InitStruct(structure,library,0);
  1057.  
  1058.     /* Call init vector */
  1059.     if(init!=NULL)
  1060.     {
  1061.       InitFunction_proto* i = (InitFunction_proto*) init;
  1062.  
  1063.       library = i( library, segList, SysBase );
  1064.     }
  1065.   }
  1066.  
  1067. #ifdef DEBUG
  1068.   KPrintF( "MyMakeLibrary -> 0x%08lx\n", (ULONG) library );
  1069. #endif
  1070.   
  1071.   /* All done */
  1072.   return library;
  1073. }
  1074.  
  1075. APTR ASMCALL
  1076. MyInitResident( REG( a1, struct Resident* resident ),
  1077.                 REG( d1, ULONG            segList ) )
  1078. {
  1079.   APTR res = NULL;
  1080.   /* This code is from AROS, except for the RTF_NATIVE part. */
  1081.  
  1082. #ifdef DEBUG
  1083.   KPrintF( "MyInitResident( 0x%08lx, 0x%08lx )\n",
  1084.            (ULONG) resident, segList );
  1085. #endif
  1086.  
  1087.   /* Check for validity */
  1088.   if(resident->rt_MatchWord != RTC_MATCHWORD ||
  1089.      resident->rt_MatchTag != resident)
  1090.     goto end;
  1091.  
  1092.   /* Depending on the autoinit flag... */
  1093.   if(resident->rt_Flags & RTF_AUTOINIT)
  1094.   {
  1095.     /* ...initialize automatically... */
  1096.     struct init
  1097.     {
  1098.       ULONG dSize;
  1099.       APTR vectors;
  1100.       APTR structure;
  1101.       APTR init;
  1102.     };
  1103.     struct init *init = (struct init *)resident->rt_Init;
  1104.     struct Library *library;
  1105.  
  1106.     /*
  1107.         Make the library. Don't call the Init routine yet, but delay
  1108.         that until we can copy stuff from the tag to the libbase.
  1109.     */
  1110.     library = MakeLibrary(init->vectors, init->structure,
  1111.                           NULL, init->dSize, segList);
  1112.  
  1113.     if(library != NULL)
  1114.     {
  1115.       /*
  1116.           Copy over the interesting stuff from the ROMtag, and set the
  1117.           library state to indicate that this lib has changed and
  1118.           should be checksummed at the next opportunity.
  1119.  
  1120.           Don't copy the priority, because a tag's priority doesn't
  1121.           mean the same as a lib's priority.
  1122.       */
  1123.       library->lib_Node.ln_Type = resident->rt_Type;
  1124.       library->lib_Node.ln_Name = resident->rt_Name;
  1125.       library->lib_Version      = resident->rt_Version;
  1126.       library->lib_IdString     = resident->rt_IdString;
  1127.       library->lib_Flags        = LIBF_SUMUSED|LIBF_CHANGED;
  1128.  
  1129.       /*
  1130.           Call the library init vector, if set.
  1131.       */
  1132.       if(init->init)
  1133.       {
  1134.         library = CallInitFunc( resident, init->init, library, segList );
  1135.       }
  1136.  
  1137.       /*
  1138.           Test the library base, in case the init routine failed in
  1139.           some way.
  1140.       */
  1141.  
  1142.       if(library != NULL)
  1143.       {
  1144.         /*
  1145.             Add the initialized module to the system.
  1146.         */
  1147.         switch(resident->rt_Type)
  1148.         {
  1149.           case NT_DEVICE:
  1150.             AddDevice((struct Device *)library);
  1151.             break;
  1152.           case NT_LIBRARY:
  1153.             AddLibrary(library);
  1154.             break;
  1155.           case NT_RESOURCE:
  1156.             AddResource(library);
  1157.             break;
  1158.         }
  1159.       }
  1160.     }
  1161.  
  1162.     res = library;
  1163.   }
  1164.   else
  1165.   {
  1166.     /* ...or let the library do it. */
  1167.  
  1168.     res = CallInitFunc( resident, resident->rt_Init, NULL, segList );
  1169.   }
  1170.  
  1171.   end:
  1172.   
  1173. #ifdef DEBUG
  1174.   KPrintF( "MyInitResident -> 0x%08lx\n", (ULONG) res );
  1175. #endif
  1176.   return res;
  1177. }
  1178.  
  1179. /*** dos.library patches follows *********************************************/
  1180.  
  1181. BPTR ASMCALL
  1182. MyInternalLoadSeg( REG( d0, BPTR  fh ),
  1183.                    REG( a0, BPTR  table ),
  1184.                    REG( a1, LONG* functionarray ),
  1185.                    REG( a2, LONG* stack ) )
  1186. {
  1187. #ifdef DEBUG
  1188.   KPrintF( "MyInternalLoadSeg( 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx )\n",
  1189.            fh, table, (ULONG) functionarray, (ULONG) stack );
  1190. #endif
  1191.  
  1192.   return OldInternalLoadSeg( fh, table, functionarray, stack );
  1193. }
  1194.  
  1195.  
  1196. BPTR ASMCALL
  1197. MyLoadSeg( REG( d1, STRPTR name ) )
  1198. {
  1199.   BPTR result;
  1200.  
  1201. #ifdef DEBUG
  1202.   KPrintF( "MyLoadSeg( %s )\n", (ULONG) name );
  1203. #endif
  1204.  
  1205.   result = OldLoadSeg( name );
  1206.  
  1207.   if( result == 0 )
  1208.   {
  1209.     result = LoadELFSeg( name, NULL );
  1210.   }
  1211.  
  1212.   return result;
  1213. }
  1214.  
  1215.  
  1216. BPTR ASMCALL
  1217. MyNewLoadSeg( REG( d1, STRPTR name ),
  1218.               REG( d2, struct TagItem* tags ) )
  1219. {
  1220.   BPTR result;
  1221.  
  1222. #ifdef DEBUG
  1223.   KPrintF( "MyNewLoadSeg( %s, %08lx )\n", (ULONG) name, (ULONG) tags );
  1224. #endif
  1225.  
  1226.   result = OldNewLoadSeg( name, tags );
  1227.  
  1228.   if( result == 0 )
  1229.   {
  1230.     result = LoadELFSeg( name, tags );
  1231.   }
  1232.  
  1233.   return result;
  1234. }
  1235.